<!DOCTYPE html>

<html lang='en'>

<head>
	<meta name="author" content="Philip Semanchuk">
	<meta name="copyright" content="All contents &copy; 2020 Philip Semanchuk">
	<meta name="keywords" content="python posix ipc semaphore shared memory message queue">

    <title>POSIX IPC for Python</title>

    <style>
        dt {
            font-family: monospace;
            font-weight: bold;
            padding-bottom: .33em;
            margin-top: 1em;
        }
        span[lang] { font-style: italic; }

        span.param {
            font-family: monospace;
            font-style: italic;
        }

        li {
            margin-top: .67em;
            margin-bottom: .67em;
        }

        pre { margin-left: 2em; }

        /* This style is only present on the local version of the readme.
           In the online version, the RSS feed is displayed. */
        div.rss { display: none; }
    </style>
</head>

<body>

<h2>POSIX IPC for Python - Semaphores, Shared Memory and Message Queues</h2>

<div class="rss">
    <a href="rss.xml"><img src="/common/images/rss.png" width="28" height="28" alt=""></a>
    <br><a href="rss.xml">RSS</a>
</div>

<p>The Python extension module <code>posix_ipc</code> gives Python access
to POSIX inter-process semaphores, shared memory and message queues on
systems that support the POSIX Realtime Extensions a.k.a. POSIX 1003.1b-1993.
That includes most (all?) Linuxes with kernel ≥ 2.6, FreeBSD ≥ 7.2, and
OpenSolaris ≥ 2008.05.
</p>

<p>macOS/OS X and other Unix-y platforms (including Windows +
<a href="http://www.cygwin.com/">Cygwin 1.7</a>) provide partial
(or partially broken) support. See <a href="#platforms">
the platform notes below</a> for more details.
</p>

<p>This module works under Python 2.7 and 3.x. It is released
under a BSD license.
</p>


<p>You can <strong>download
<a href="posix_ipc-1.0.5.tar.gz">posix_ipc version 1.0.5</a>
</strong>
<a href="posix_ipc-1.0.5.md5.txt">[MD5 sum]</a>
<a href="posix_ipc-1.0.5.sha1.txt">[SHA1 sum]</a>

which contains the source code, setup.py, installation instructions, tests, and
<a href="#samples">sample code</a>. The exact same
<a href="https://pypi.python.org/pypi/posix_ipc">posix_ipc tarball is also
available on PyPI</a>. You can also find
<a href='https://github.com/osvenskan/posix_ipc/'>the
<code>posix_ipc</code> source code on GitHub</a>.
</p>

<p>
You might want to read
<a href="history.html">all of the changes in this version</a> and
about some <a href="#KnownBugs">known bugs</a>.
</p>

<p>Note that this module doesn't support unnamed (anonymous) POSIX
semaphores.
</p>

<p>You might be interested in the very similar module
<a href="/philip/sysv_ipc/"><code>sysv_ipc</code> which
provides Python access to IPC using System V semaphores, shared memory and
message queues</a>.
System V IPC has broader OS support but is not as easy to use.
</p>

<h2>Module <code>posix_ipc</code> Documentation</h2>

<p>Jump to <a href="#semaphore">semaphores</a>,
<a href="#shared_memory">shared memory</a>, or
<a href="#message_queue">message queues</a>.</p>

<h3>Module Functions</h3>

<dl>
    <dt>unlink_semaphore(name)<br>
        unlink_shared_memory(name)<br>
        unlink_message_queue(name)
    </dt>
    <dd>Convenience functions that unlink the IPC object described
        by <span class="param">name</span>.</dd>
</dl>


<h3>Module Constants</h3>

<dl>
    <dt>O_CREX, O_CREAT, O_EXCL and O_TRUNC</dt>
    <dd>These flags are used when creating IPC objects.
        All except <code>O_CREX</code> are bitwise unique and can be
        ORed together. <code>O_CREX</code> is shorthand for
        <code>O_CREAT | O_EXCL</code>.

        <p><code>O_TRUNC</code> is only useful when
        creating SharedMemory objects.</p>
    </dd>

    <dt>PAGE_SIZE</dt>
    <dd>The operating system's memory page size, in bytes. It's probably a
        good idea to make shared memory segments some multiple of this size.
    </dd>

    <dt>SEMAPHORE_TIMEOUT_SUPPORTED</dt>
    <dd>True if the underlying OS supports <code>sem_timedwait()</code>. If False, all
        timeouts &gt; 0 passed to a semaphore's <code>acquire()</code> method are
        treated as infinity.

        <p>As far as I know, this is only False under macOS.</p>
    </dd>

    <dt>SEMAPHORE_VALUE_SUPPORTED</dt>
    <dd>True if the underlying OS supports <code>sem_getvalue()</code>. If False,
        accessing the <code>value</code> attribute on a <code>Semaphore</code> instance
        will raise an AttributeError.

        <p>As far as I know, this is only False under macOS.</p>
    </dd>

    <dt>SEMAPHORE_VALUE_MAX</dt>
    <dd>The maximum value that can be assigned to a semaphore.
    </dd>

    <dt>MESSAGE_QUEUES_SUPPORTED</dt>
    <dd>True if the underlying OS supports message queues, False otherwise.
    </dd>

    <dt>QUEUE_MESSAGES_MAX_DEFAULT</dt>
    <dd>The default value for a message queue's <code>max_messages</code>
        attribute. This can be quite small under Linux (e.g. 10)
        but is usually LONG_MAX everywhere else.
    </dd>

    <dt>QUEUE_MESSAGE_SIZE_MAX_DEFAULT</dt>
    <dd>The default value for a message queue's <code>max_message_size</code>
        attribute. This is 8k (or possibly smaller under Linux).
    </dd>

    <dt>QUEUE_PRIORITY_MAX</dt>
    <dd>The maximum message queue message priority.
    </dd>

    <dt>USER_SIGNAL_MIN, USER_SIGNAL_MAX</dt>
    <dd>The constants define a range of signal values reserved for
        use by user applications (like yours). They're available only on
        systems that support the POSIX Realtime Signals Extension. Most
        systems do; NetBSD versions prior to 6.0 are a notable exception.
    </dd>

    <dt>VERSION</dt>
    <dd>The module version string, e.g. <code>'0.9.8'</code>. This is also
    available as <code>__version__</code>.
    </dd>
</dl>

<h3>Module Errors</h3>

<p>In addition to standard Python errors (e.g. <code>ValueError</code>),
this module raises custom errors. These errors cover
situations specific to IPC.
</p>


<dl>
    <dt>Error</dt>
    <dd>The base error class for all the custom errors in this module.
    </dd>

    <dt>SignalError</dt>
    <dd>Raised when a waiting call (e.g. <code>sem.acquire()</code>) is
        interrupted by a signal other than KeyboardInterrupt.
    </dd>

    <dt>PermissionsError</dt>
    <dd>Indicates that you've attempted something that the permissions on the
        IPC object don't allow.
    </dd>

    <dt>ExistentialError</dt>
    <dd>Indicates an error related to the existence or non-existence of
        an IPC object.
    </dd>

    <dt>BusyError</dt>
    <dd>Raised when a call times out.
    </dd>
</dl>


<h3 id="semaphore">The Semaphore Class</h3>

<p>This is a handle to a semaphore.</p>

<h4>Methods</h4>

<dl>
    <dt>Semaphore(name, [flags = 0, [mode = 0600, [initial_value = 0]]])</dt>
    <dd>Creates a new semaphore or opens an existing one.

        <p><span class="param">name</span> must be <code>None</code> or
            a string. If it is <code>None</code>, the module chooses a random
            unused name. If it is a string, it
            should begin with a slash and be valid according
        to pathname rules on your system, e.g.
        <code>/wuthering_heights_by_semaphore</code>
        </p>

        <p>The <span class="param">flags</span> specify whether you want to create a
            new semaphore or open an existing one.
        </p>

        <ul>
            <li>With <span class="param">flags</span> set to the default of <code>0</code>, the module attempts
                to open an existing semaphore and raises an error if that semaphore
                doesn't exist.
            </li>

            <li>With <span class="param">flags</span> set to <code>O_CREAT</code>,
                the module opens the semaphore if it exists (in which case mode and
                initial value are ignored) or creates it if it doesn't.
            </li>

            <li>With <span class="param">flags</span> set to <code>O_CREAT | O_EXCL</code>
                (or <code>O_CREX</code>),
                the module creates a new semaphore identified by
                <span class="param">name</span>. If a
                semaphore with that name already exists, the call raises
                an <code>ExistentialError</code>.
            </li>
        </ul>
    </dd>


    <dt>acquire([timeout = None])</dt>
    <dd>Waits (conditionally) until the semaphore's value is &gt; 0 and then returns,
        decrementing the semaphore.

        <p>The <span class="param">timeout</span> (which can be a float) specifies how
            many seconds this call should wait, if at all.
        </p>

        <ul>
            <li>A <span class="param">timeout</span> of None (the default)
                implies no time limit. The call will not return until its wait
                condition is satisfied.
            </li>

            <li>When <span class="param">timeout</span> is 0, the call
                immediately raises a <code>BusyError</code>
                if asked to wait. Since it will return immediately if not
                asked to wait, this can be thought of as "non-blocking" mode.

                <p>This behavior is unaffected by whether or not the
                	platform supports <code>sem_timedwait()</code>
                	(see below).
                </p>
            </li>

            <li>When the <span class="param">timeout</span> is &gt; 0, the call
                will wait no longer than <span class="param">timeout</span>
                seconds before either returning (having acquired the semaphore)
                or raising a <code>BusyError</code>.

                <p>On platforms that don't support the <code>sem_timedwait()</code> API,
                   a <span class="param">timeout</span> &gt; 0 is treated as
                   infinite. The call will not return until its wait
                   condition is satisfied.
                </p>

                <p>Most platforms provide <code>sem_timedwait()</code>. macOS is a
                    notable exception. The module's Boolean constant
                    <code>SEMAPHORE_TIMEOUT_SUPPORTED</code>
                    is True on platforms that support <code>sem_timedwait()</code>.
                </p>
            </li>
        </ul>
    </dd>

    <dt>release()</dt>
    <dd>
        Releases (increments) the semaphore.
    </dd>

    <dt>close()</dt>
    <dd>
        Closes the semaphore, indicating that the current <em>process</em> is
        done with the semaphore. The effect of subsequent use of the semaphore
        by the current process is undefined. Assuming it still exists,
        (see <code>unlink()</code>, below) the semaphore can be re-opened.

        <p>You must call <code>close()</code> explicitly; it is
           <strong>not</strong> called automatically
            when a Semaphore object is garbage collected.
        </p>
    </dd>

    <dt id="unlink_semaphore">unlink()</dt>
    <dd>
        Destroys the semaphore, with a caveat. If any processes have the semaphore
        open when unlink is called, the call to unlink returns immediately
        but destruction of the semaphore is postponed until all processes
        have closed the semaphore.

        <p>Note, however, that once a semaphore has been unlinked,
            calls to <code>open()</code> with the same name should
            refer to a new semaphore. Sound confusing? It is, and you'd
            probably be wise structure your code so as to avoid
            this situation.
        </p>
    </dd>
</dl>

<h4>Attributes</h4>

<dl>
    <dt>name (read-only)</dt>
    <dd>The name provided in the constructor.</dd>

    <dt>value (read-only)</dt>
    <dd>The integer value of the semaphore. Not available on macOS.
        (See <a href="#platforms">Platforms</a>)
    </dd>
</dl>

<h4>Context Manager Support</h4>

<p>These semaphores support the context manager protocol so they can be
used with Python's <code>with</code> statement, just like
Python's <code>threading.Semaphore</code>. For instance --
</p>

<pre>
with posix_ipc.Semaphore(name) as sem:
    # Do something...
</pre>

<p>Entering the context acquires the semaphore, exiting the context releases
	the semaphore. See <code>demo4/child.py</code> for a complete example. The context
	manager only manages acquisition and release. If you create a new semaphore
	as part of executing the <code>with</code> statement, you must explicitly unlink it.
</p>


<h3 id="shared_memory">The SharedMemory Class</h3>

<p>This is a handle to a shared memory segment. POSIX shared memory segments
masquerade as files, and so the handle to a shared memory segment is just
a file descriptor that can be mmapped.
</p>

<h4>Methods</h4>

<dl>
    <dt>SharedMemory(name, [flags = 0, [mode = 0600, [size = 0, [read_only = false]]]])</dt>
    <dd>Creates a new shared memory segment or opens an existing one.

        <p><span class="param">name</span> must be <code>None</code> or
            a string. If it is <code>None</code>, the module chooses a random
            unused name. If it is a string, it
            should begin with a slash and be valid according
        to pathname rules on your system, e.g.
        <code>/four_yorkshiremen_sharing_memories</code>
        </p>

        <p>On some systems you need to have write access to the path.</p>

        <p>The <span class="param">flags</span> specify whether you want to create a
            new shared memory segment or open an existing one.
        </p>

        <ul>
            <li>With <span class="param">flags</span> set to the default of <code>0</code>, the module attempts
                to open an existing segment and raises an error if that segment
                doesn't exist.
            </li>

            <li>With <span class="param">flags</span> set to <code>O_CREAT</code>,
                the module opens the segment if it exists or creates it if it doesn't.
            </li>

            <li>With <span class="param">flags</span> set to <code>O_CREAT | O_EXCL</code>
                (or <code>O_CREX</code>),
                the module creates a new shared memory segment identified by
                <span class="param">name</span>. If a
                segment with that name already exists, the call raises
                an <code>ExistentialError</code>.
            </li>
        </ul>

        <p>If you pass a non-zero size, the segment will be (re)sized accordingly, regardless
        	of whether or not it's a new or existing segment. Prior to version 1.0.4, this documentation incorrectly stated that size was ignored if the segment already existed.
        </p>
        <p>
        	To (re)size the segment, <code>posix_ipc</code> calls <code>ftruncate()</code>.
        	The same function is available to Python via
        	<a href='https://docs.python.org/3/library/os.html#os.ftruncate'><code>os.ftruncate()</code></a>.
        	If you prefer to handle segment (re)sizing yourself, leave the
        	<code>SharedMemory</code> parameter <code>size</code> at its default of <code>0</code> and
        	call <code>os.ftruncate()</code> when and how you like.
        </p>

        <p>Note that under macOS (up to and including 10.12 at least), you can
        	only call <code>ftruncate()</code> once on a segment during its lifetime.
        	This is a limitation of macOS, not <code>posix_ipc</code>.
        </p>

        <p>When opening an existing shared memory segment, one can also specify
            the flag <code>O_TRUNC</code>
            to truncate the shared memory to zero bytes. macOS does not
            support <code>O_TRUNC</code>.
        </p>
    </dd>


    <dt>close_fd()</dt>
    <dd>
        Closes the file descriptor associated with this SharedMemory
        object. Calling <code>close_fd()</code> is the same as calling
        <code><a href="https://docs.python.org/2/library/os.html#os.close">os.close()</a></code>
        on a SharedMemory object's <code>fd</code> attribute.

        <p>You must call <code>close_fd()</code> or <code>os.close()</code>
            explicitly; the file descriptor is <strong>not</strong> closed
            automatically when a SharedMemory object is garbage collected.
        </p>

        <p>Closing the file descriptor has no effect on any <code>mmap</code>
            objects that were created from it. See the demo for an
            example.
        </p>
    </dd>


    <dt>unlink()</dt>
    <dd>
        Marks the shared memory for destruction once all processes have unmapped it.

        <p>
        <a href="http://www.opengroup.org/onlinepubs/009695399/functions/shm_unlink.html">The
        POSIX specification for <code>shm_unlink()</code></a> says, "Even if the object
        continues to exist after the last shm_unlink(), reuse of the name shall subsequently
        cause shm_open() to behave as if no shared memory object of this name exists
        (that is, shm_open() will fail if O_CREAT is not set, or will create a new shared
        memory object if O_CREAT is set)."
        </p>

        <p>I'll bet a virtual cup of coffee that this tricky part of the
        standard is not well or consistently implemented in every OS. Caveat emptor.
        </p>
    </dd>
</dl>

<h4>Attributes</h4>

<dl>
    <dt>name (read-only)</dt>
    <dd>The name provided in the constructor.</dd>
    <dt>fd (read-only)</dt>
    <dd>The file descriptor that represents the memory segment.</dd>
    <dt>size (read-only)</dt>
    <dd>The size (in bytes) of the shared memory segment.</dd>
</dl>

<h3 id="message_queue">The MessageQueue Class</h3>

<p>This is a handle to a message queue.</p>

<h4>Methods</h4>

<dl>
    <dt>MessageQueue(name, [flags = 0, [mode = 0600, [max_messages = QUEUE_MESSAGES_MAX_DEFAULT, [max_message_size = QUEUE_MESSAGE_SIZE_MAX_DEFAULT, [read = True, [write = True]]]]]])</dt>
    <dd>Creates a new message queue or opens an existing one.

        <p><span class="param">name</span> must be <code>None</code> or
            a string. If it is <code>None</code>, the module chooses a random
            unused name. If it is a string, it
            should begin with a slash and be valid according
        to pathname rules on your system, e.g.
        <code>/my_message_queue</code>
        </p>

        <p>On some systems you need to have write access to the path.</p>

        <p>The <span class="param">flags</span> specify whether you want to
            create a new queue or open an existing one.
        </p>

        <ul>
            <li>With <span class="param">flags</span> set to the default of
                <code>0</code>, the module attempts
                to open an existing queue and raises an error if that queue
                doesn't exist.
            </li>

            <li>With <span class="param">flags</span> set to <code>O_CREAT</code>,
                the module opens the queue if it exists (in which case
                <span class="param">size</span> and <span class="param">mode</span>
                are ignored) or creates it if it doesn't.
            </li>

            <li>With <span class="param">flags</span> set to <code>O_CREAT | O_EXCL</code>
                (or <code>O_CREX</code>),
                the module creates a new message queue identified by
                <span class="param">name</span>. If a
                queue with that name already exists, the call raises
                an <code>ExistentialError</code>.
            </li>
        </ul>

        <p><span class="param">Max_messages</span> defines how many messages
            can be in the queue at one time. When the queue is full,
            calls to <code>.send()</code> will wait.
        </p>

        <p><span class="param">Max_message_size</span> defines the maximum
            size (in bytes) of a message.
        </p>

        <p><span class="param">Read</span> and
            <span class="param">write</span>
            default to True. If <span class="param">read/write </span>
            is False, calling <code>.receive()/.send()</code> on this object
            is not permitted.
            This doesn't affect other handles to the same queue.
        </p>
    </dd>

    <dt>send(message, [timeout = None, [priority = 0]])</dt>
    <dd>
        Sends a message via the queue.

        <p>The <span class="param">message</span> string can contain embedded
            NULLs (ASCII <code>0x00</code>). Under Python 3, the message can
            also be a bytes object.
        </p>

        <p>The <span class="param">timeout</span> (which can be a float)
            specifies how many seconds this call should wait if the
            queue is full. Timeouts are irrelevant when the <code>block</code>
            flag is False.
        </p>

        <ul>
            <li>A <span class="param">timeout</span> of None (the default)
                implies no time limit. The call will not return until the
                message is sent.
            </li>

            <li>When <span class="param">timeout</span> is 0, the call
                immediately raises a <code>BusyError</code>
                if asked to wait.
            </li>

            <li>When the <span class="param">timeout</span> is &gt; 0, the call
                will wait no longer than <span class="param">timeout</span>
                seconds before either returning (having sent the message)
                or raising a <code>BusyError</code>.
            </li>
        </ul>

        <p>The <span class="param">priority</span> allows you to order
            messages in the queue. The highest priority message is received
            first. By default, messages are sent at the lowest priority (0).
        </p>
    </dd>

    <dt>receive([timeout = None])</dt>
    <dd>
        Receives a message from the queue, returning a tuple of
        <code>(message, priority)</code>. Messages are received in the order of
        highest priority to lowest, and in FIFO order for messages of
        equal priority.

        Under Python 3, the returned message is a bytes object.

        <p>If the queue is empty, the call will not return immediately.
        The optional <span class="param">timeout</span> parameter controls the
        wait just as for the function <code>send()</code>. It defaults to None.
        </p>
    </dd>

    <dt>request_notification([notification = None])</dt>
    <dd>Depending on the parameter, requests or cancels notification from the
        operating system when the queue changes from empty to non-empty.

        <ul>
            <li>When <span class="param">notification</span> is not provided
            	or <code>None</code>, any existing notification request is
                cancelled.
            </li>

            <li>When <span class="param">notification</span> is an
                integer, notification will be sent as a signal of this
                value that can be caught using a signal handler installed
                with <code>signal.signal()</code>.
            </li>

            <li>When <span class="param">notification</span> is a tuple
                of <code>(function, param)</code>, notification will be sent
                by invoking <code><em>function(param)</em></code> in a new
                thread.
            </li>
        </ul>

        <p>Message queues accept only one notification request at a time.
            If another process has already requested notifications from
            this queue, this call will fail with a <code>BusyError</code>.
        </p>

        <p>The operating system delivers (at most) one notification
            per request. If you want subsequent notifications, you must
            request them by calling <code>request_notification()</code> again.
        </p>
    </dd>

    <dt>close()</dt>
    <dd>
        Closes this reference to the queue.

        <p>You must call <code>close()</code> explicitly; it is
           <strong>not</strong> called automatically
            when a MessageQueue object is garbage collected.
        </p>
    </dd>

    <dt>unlink()</dt>
    <dd>
        Requests destruction of the queue. Although the call returns
        immediately, actual destruction of the queue is postponed until all
        references to it are closed.
    </dd>
</dl>

<h4>Attributes</h4>

<dl>
    <dt>name (read-only)</dt>
    <dd>The name provided in the constructor.</dd>
    <dt>mqd (read-only)</dt>
    <dd>The message queue descriptor that represents the queue.</dd>
    <dt>block</dt>
    <dd>When True (the default), calls to <code>.send()</code> and
        <code>.receive()</code> may wait (block) if they cannot immediately
        satisfy the send/receive request. When <code>block</code> is False,
        the module will raise <code>BusyError</code>
        instead of waiting.
    </dd>
    <dt>max_messages (read-only)</dt>
    <dd>The maximum number of messages the queue can hold.</dd>
    <dt>max_message_size (read-only)</dt>
    <dd>The maximum message size (in bytes).</dd>
    <dt>current_messages (read-only)</dt>
    <dd>The number of messages currently in the queue.</dd>
</dl>


<h3>Usage Tips</h3>

<h4 id="tests">Tests</h4>

<p>This module comes with fairly complete unit tests in the <code>tests</code>
directory. To run them, install <code>posix_ipc</code> and then run this command
from the same directory as <code>setup.py</code>:<br>
<code>python -m unittest discover</code>
</p>

<h4 id="samples">Sample Code</h4>

<p>This module comes with four demonstrations. The first (in the
directory <code>demo</code>) shows how to use shared memory and semaphores.
The second (in the directory <code>demo2</code>) shows how to use
message queues. The third (<code>demo3</code>) shows how to use message queue
notifications. The fourth (<code>demo4</code>) shows how to use a semaphore in
a context manager.
</p>

<h4>Nobody Likes a Mr. Messy</h4>

<p>IPC objects are a little different from most Python objects
and therefore require a little more care on the part of the programmer. When a
program creates a IPC object, it creates something that
resides <em>outside of its own process</em>, just like a file on a hard drive. It
won't go away when your process ends unless you explicitly remove it. And since many
operating systems don't even give you a way to enumerate existing POSIX IPC
entities, it might be hard to figure out what you're leaving behind.
</p>

<p>In short, remember to clean up after yourself.</p>

<h4>Semaphores and References</h4>

<p>I know it's <em>verboten</em> to talk about pointers in Python, but I'm
going to do it anyway.
</p>

<p>Each Semaphore object created by this module contains a C pointer to
the IPC object created by the system. When you call <code>sem.close()</code>,
the object's internal pointer is set to <code>NULL</code>. This leaves the
object in a not-quite-useless state. You can still call <code>sem.unlink()</code>
or print <code>sem.name</code>, but calls to <code>sem.aquire()</code> or
<code>sem.release()</code> will raise an <code>ExistentialError</code>.
</p>

<p>If you know you're not going to use a Semaphore object after calling
<code>sem.close()</code> or <code>sem.unlink()</code>, you could you set your
semaphore variable to the return from the function (which is always
<code>None</code>) like so:
</p>

<pre>
    my_sem = my_sem.close()
</pre>

<p>That will ensure you don't have any nearly useless objects laying around
that you might use by accident.
</p>

<p>This doesn't apply to shared memory and message queues because they're
referenced at the C level by a file descriptor rather than a pointer.
</p>

<h4>Permissions</h4>

<p>It appears that the read and write mode bits on IPC objects are
ignored by the operating system. For instance, on macOS, OpenSolaris and
Linux one can write to semaphores and message queues with a mode of
<code>0400</code>.
</p>


<h4>Message Queues</h4>

<p>When creating a new message queue, you specify a maximum message size
which defaults to <code>QUEUE_MESSAGE_SIZE_MAX_DEFAULT</code> (currently 8192
bytes). You can create a queue with a larger value, but be aware that
<code>posix_ipc</code> allocates a buffer the size of the maximum message size
every time <code>receive()</code> is called.
</p>

<h4>Consult Your Local <code>man</code> Pages</h4>

<p>The posix_ipc module is just a wrapper around your system's API. If your
system's implementation has quirks, the <code>man</code> pages for
<code>sem_open, sem_post,
sem_wait, sem_close, sem_unlink, shm_open, shm_unlink, mq_open, mq_send
mq_receive, mq_getattr, mq_close, mq_unlink</code> and <code>mq_notify</code> will
probably cover them.
</p>

<h4>Last But Not Least</h4>

<p>For Pythonistas &ndash;</p>
<ul>
    <li><a href="https://www.youtube.com/watch?v=VKHFZBUTA4k">A meditation on the
    	inaccuracy of shared memories</a>
    </li>
</ul>

<h3><a id="KnownBugs">Known Bugs</a></h3>

<p>I don't know of any bugs in this code, but FreeBSD users should check the
platform notes.
</p>

<h3>Support for Older Pythons</h3>

<p>
If you need to support Python &lt; 2.7, try
<a href="posix_ipc-0.9.9.tar.gz">posix_ipc version 0.9.9</a>
<a href="posix_ipc-0.9.9.md5.txt">[MD5 sum]</a>
<a href="posix_ipc-0.9.9.sha1.txt">[SHA1 sum]</a>.
</p>

<h2 id="platforms">Platform Notes</h2>

<p>This module is just a wrapper around the operating system's functions,
so if the operating system doesn't provide a function, this module can't
either. The POSIX Realtime Extensions (POSIX 1003.1b-1993) are, as the name
implies, an extension to POSIX and so a platform can claim "<em>POSIX
conformance</em>" and still not support any or all of the IPC functions.
</p>

<dl>
    <dt>Linux with kernel ≥ 2.6</dt>
    <dd>All features supported.</dd>

    <dt>OpenSolaris ≥ 2008.05</dt>
    <dd>All features supported.</dd>

    <dt>FreeBSD ≥ 7.2</dt>
    <dd>All features supported.

        <p>Under 7.2, <code>posix_ipc</code>'s demos fail unless they're run as
            root. It's a simple permissions problem. Prefix the IPC object
            names with <code>/tmp</code> in <code>params.txt</code> and the problem
            goes away. I didn't see this behavior under FreeBSD 8.0, so it
            must have been fixed at some point.
        </p>

        <p>If you don't have the <code>sem</code> and <code>mqueuefs</code> kernel
            modules loaded, you'll get a message like this (or something
            similarly discouraging) when you
            try to create a semaphore or message queue:<br>
            <code>Bad system call: 12 (core dumped)</code>
        </p>

        <p>Type <code>kldstat</code> to list loaded modules, and
            <code>kldload sem</code> or <code>kldload mqueuefs</code> if you need
            to load either of these. BTW,
            <a href="http://www.freebsd.org/cgi/man.cgi?query=mqueuefs&amp;apropos=0&amp;sektion=5&amp;manpath=FreeBSD+8.0-stable&amp;format=html">mqueuefs</a> has
            some cool features.
        </p>

        <p>
        Prior to 7.2, FreeBSD POSIX semaphore support was
        <a href="http://www.freebsd.org/cgi/query-pr.cgi?pr=127545">broken</a>.
        </p>

        <p>Under FreeBSD 11.1, I have seen segfaults during the message queue
        	threaded notification rearm test. I don't know if <code>posix_ipc</code>
        	or FreeBSD (or both!) are culprits.
        </p>

    </dd>

    <dt>macOS/OS X (up to and including 10.12)</dt>
    <dd>
    	<p>macOS' implementation of POSIX IPC has some significant holes.
    		Message queues are not supported at all. Also,
        <code>sem_getvalue()</code> and <code>sem_timedwait()</code> are not
        supported.
    	</p>
    </dd>

    <dt>Windows + Cygwin 1.7</dt>

    <dd><a href="http://www.cygwin.com/">Cygwin</a> is a Linux-like
        environment for Windows.

        <p>Versions of Cygwin prior to 1.7 didn't support POSIX IPC.
            Under Cygwin 1.7 beta 62 (released in early October 2009),
            <code>posix_ipc</code> compiles and runs both demos.
        </p>
    </dd>
</dl>


</body>
</html>
